home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / sos3-2.lha / src / dir / dir_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-23  |  30.1 KB  |  1,041 lines

  1. /* --------------------------------------------------------------------------
  2.  * Copyright 1992 by Forschungszentrum Informatik (FZI)
  3.  *
  4.  * You can use and distribute this software under the terms of the licence
  5.  * you should have received along with this program.
  6.  * If not or if you want additional information, write to
  7.  * Forschungszentrum Informatik, "STONE", Haid-und-Neu-Strasse 10-14,
  8.  * D-7500 Karlsruhe 1, Germany.
  9.  * --------------------------------------------------------------------------
  10.  */
  11. // **************************************************************************
  12. // Module dir_main                                           Juergen Uhl (ju)
  13. //
  14. // **************************************************************************
  15. // SOS directory browser
  16. // **************************************************************************
  17.  
  18. #include <sys/file.h>          // avoid warning for flock
  19. #include <libc.h>
  20. #include <stdio.h>
  21.  
  22. #include "sys.h"
  23. #include "smg.h"
  24. #include "sos.h"
  25.  
  26. #include "dir_err.h"
  27. #include "dir_use.h"
  28.  
  29. #define XTFUNCPROTO
  30.  
  31. #include <X11/IntrinsicP.h>
  32. #include <X11/Shell.h>
  33. extern "C" {
  34. #include <X11/Xaw/List.h>
  35. #include <X11/Xaw/Form.h>
  36. #include <X11/Xaw/Command.h>
  37. #include <X11/Xaw/Label.h>
  38. #include <X11/Xaw/Text.h>
  39. #define ASCII_STRING
  40. #include <X11/Xaw/AsciiText.h>
  41. #include <X11/Xaw/Viewport.h>
  42. }
  43. #include <X11/StringDefs.h>
  44. #include <X11/cursorfont.h>
  45.  
  46. #undef TRUE
  47. #undef FALSE
  48.  
  49. // ************************  Types and Objects  *************************
  50.  
  51. const int default_distance = 4;
  52. Pixel red_pxl, green_pxl, blue_pxl;
  53.  
  54. struct object_menu
  55. {  sos_Object o;
  56.    Widget w;
  57.    sos_Bool is_open;
  58.    char *path;
  59.    int nr_comps;
  60.    sos_Directory parent;
  61.    sos_String name;
  62.    sos_String *names;
  63.    char **sl;
  64.  
  65.    object_menu(){}
  66.    ~object_menu();
  67. };
  68.  
  69. static int object_nr = 1;
  70.  
  71. struct object_menu_item {sos_String name; char *s;};
  72. static struct omi_list
  73. {  object_menu_item *omi;
  74.    int nr_items;
  75.  
  76.    omi_list () {nr_items = 0;}
  77.  
  78.    void      clear();
  79.    void      insert (sos_String name, char *s);
  80.    void      print (char *s);
  81.    void      print (smg_String &s);
  82.    void      make_object_menu (object_menu *om);
  83.  
  84. } omis;
  85.  
  86. enum ocmd_cmds {ocmd_DIRECTORY, ocmd_NEW, ocmd_DELETE,
  87.         ocmd_MOVE, ocmd_REMOVE,
  88.             ocmd_QUIT, ocmd_CLOSE};
  89. static char *ocmd_menu_items [8] =
  90.             {"Directory", "new", "delete",
  91.          "move", "remove", "quit", "close"};
  92. static Widget ocmd_menu;
  93. static object_menu *ocmd_current_menu;
  94. static ocmd_cmds ocmd_cmd;
  95.  
  96. static class displayed_object_list
  97. {  displayed_object_list *next;
  98.    object_menu *om;
  99.    Widget w;
  100. public:
  101.    int number;
  102.  
  103.    displayed_object_list () {number = 0;}
  104.  
  105.    void        insert (object_menu *om, Widget w);
  106.    void        remove (object_menu *om);
  107.    Widget    widget (sos_Object o);
  108.    object_menu*    menu (sos_Object o);
  109. } displayed_objects;
  110.  
  111. struct position
  112. {  int x, y;
  113.    static position root ();
  114.    static position at_widget (Widget w);
  115.    static position next_to (Widget w);
  116. };
  117.  
  118. static const int nr_menues = 1;
  119. static Widget     menu_header[nr_menues];
  120. static Widget     menu_list[nr_menues];
  121. enum hdr_cmds {hdr_FILE};
  122. static char*    menu_header_items [nr_menues] = {"File"};
  123. enum file_cmds {file_ROOT, file_QUIT};
  124. static char*    menu_list_items [nr_menues] [3] =
  125.             {  {"root", "quit"}
  126.         };
  127. static int    open_menu = nr_menues;
  128.  
  129. const int ac_max = 30;
  130. Arg      al[ac_max];
  131. int      ac;
  132.  
  133. Widget app_form_wdgt, form_wdgt;
  134.  
  135. static struct
  136. {  Widget main, txt;
  137. } txt_menu_wdgts;
  138.  
  139. const int    txt_length = 256;
  140. char        txt_string [txt_length+1];
  141.  
  142. Widget        info_line_wdgt;
  143. const int    info_length = 80;
  144. char        info_string [info_length+1];
  145.  
  146. // ***********************  Global Functions  ***************************
  147.  
  148. static void      draw_frame (Display *disp, Window win, GC dragGC,
  149.                   int win_x, int win_y,
  150.                   Dimension width, Dimension height);
  151. static void      query_pointer (Display *disp, Window win,
  152.                    int &win_x, int &win_y,
  153.                    int xoffs, int yoffs);
  154. static void      drag_object (Widget w,
  155.                    caddr_t client_data,
  156.                    XEvent *event);
  157.  
  158. static char*      elem_path (char *parent_path, sos_String name);
  159.  
  160. static void      object_callback (Widget w,
  161.                    caddr_t client_data,
  162.                    caddr_t call_data);
  163. static void      ocmd_callback (Widget w,
  164.                  caddr_t client_data,
  165.                  caddr_t call_data);
  166.  
  167. static void      display_elements (sos_Directory d);
  168. static void      display_object_menu (sos_Object o,
  169.                        sos_Directory parent,
  170.                        sos_String name,
  171.                        char *path,
  172.                        position pos);
  173. static void      redisplay_object_menu (object_menu *om, sos_Bool moved = FALSE);
  174. static void      delete_object_menu (object_menu *om);
  175.  
  176. static void      menu_list_callback (Widget w,
  177.                       caddr_t client_data,
  178.                       caddr_t call_data);
  179. static void      menu_header_callback (Widget w,
  180.                     caddr_t client_data,
  181.                     caddr_t call_data);
  182.  
  183. static void      txt_cancel_callback (Widget w,
  184.                        caddr_t client_data,
  185.                        caddr_t call_data);
  186. static void      txt_do_callback (Widget w,
  187.                    caddr_t client_data,
  188.                    caddr_t call_data);
  189. static void      display_txt_menu();
  190.  
  191. static void      display_root();
  192. static void      display_info (err_msg msg);
  193.  
  194. static void      install_header_menues ();
  195. static void      install_ocmd_menu ();
  196. static void      install_dialogues ();
  197.  
  198. // **********************  SetValue Arguments  **************************
  199.  
  200. void inline inc_ac()
  201. {  if (ac >= ac_max)
  202.    {  fprintf (stderr, "argument overflow\n");
  203.       exit (1);
  204.    }
  205.    ac++;
  206. }
  207.  
  208. // ***************************  Dragging  *******************************
  209.  
  210. void draw_frame (Display *disp, Window win, GC dragGC,
  211.          int win_x, int win_y,
  212.          Dimension width, Dimension height)
  213. {  XDrawRectangle (disp, win, dragGC, win_x, win_y, width, height);
  214. }
  215.  
  216. void inline query_pointer (Display *disp, Window win,
  217.                int &win_x, int &win_y,
  218.                int xoffs, int yoffs)
  219. {  Window    rootwin, childwin;
  220.    int        root_x, root_y;
  221.    unsigned int    mask;
  222.  
  223.    XQueryPointer (disp, win,
  224.           &rootwin, &childwin,
  225.           &root_x, &root_y,
  226.           &win_x, &win_y, &mask);
  227.    win_x -= xoffs; if (win_x < 0) win_x = 0;
  228.    win_y -= yoffs; if (win_y < 0) win_y = 0;
  229. }
  230.  
  231. void drag_object (Widget w, caddr_t, XEvent *event)
  232. {  XEvent    ev;
  233.    Widget    parent = XtParent (w);
  234.    Display    *disp = XtDisplay (parent);
  235.    Window     win = XtWindow (parent);
  236.    GC        dragGC;
  237.    Dimension    width, height, borderwidth;
  238.    int        win_x, win_y;
  239.    int        xoffs, yoffs;
  240.    static int    initGC = TRUE;
  241.  
  242.  
  243.    if (event->xbutton.button != 2) return;
  244.  
  245.    // GC beim ersten Aufruf initialisieren
  246.    if (initGC == TRUE)
  247.    { 
  248.       dragGC = XCreateGC (disp, win, 0, NULL);
  249.       XSetForeground (disp, dragGC, BlackPixel (disp, 0));
  250.       XSetSubwindowMode (disp, dragGC, IncludeInferiors);
  251.       XSetFunction (disp, dragGC, GXxor);
  252.    }
  253.  
  254.    ac=0;
  255.    XtSetArg (al[ac], XtNwidth, &width); inc_ac();
  256.    XtSetArg (al[ac], XtNheight, &height); inc_ac();
  257.    XtSetArg (al[ac], XtNborderWidth, &borderwidth); inc_ac();
  258.    XtGetValues (w, al, ac);
  259.  
  260.    xoffs = event->xbutton.x + borderwidth;
  261.    yoffs = event->xbutton.y + borderwidth;
  262.  
  263.    query_pointer (disp, win, win_x, win_y, xoffs, yoffs);
  264.    draw_frame (disp, win, dragGC, win_x, win_y, width, height);
  265.  
  266.    XChangeActivePointerGrab (disp,
  267.                  (unsigned int) (ButtonReleaseMask |
  268.                                              ButtonMotionMask |
  269.                                              OwnerGrabButtonMask),
  270.                  XCreateFontCursor (disp, XC_fleur),
  271.                  CurrentTime);
  272.    while (TRUE)
  273.    {  XtNextEvent (&ev);
  274.       switch (ev.type)
  275.       {  case MotionNotify:
  276.         draw_frame (disp, win, dragGC, win_x, win_y, width, height);
  277.         query_pointer (disp, win, win_x, win_y, xoffs, yoffs);
  278.         draw_frame (disp, win, dragGC, win_x, win_y, width, height);
  279.         break;
  280.      case ButtonRelease:
  281.         if (ev.xbutton.button == 2)
  282.         {  draw_frame (disp, win, dragGC, win_x, win_y, width, height);
  283.            query_pointer (disp, win, win_x, win_y, xoffs, yoffs);
  284.  
  285.            XtMoveWidget (w, win_x, win_y);
  286.            XRaiseWindow (XtDisplay (w), XtWindow (w));
  287.            ac=0;
  288.            XtSetArg (al[ac], XtNhorizDistance, win_x); inc_ac();
  289.            XtSetArg (al[ac], XtNvertDistance, win_y); inc_ac();
  290.            XtSetValues (w, al, ac);
  291.            XtUnmanageChild (w);
  292.            XtManageChild (w);
  293.            return;
  294.         }
  295.         break;
  296.       }
  297.    }
  298. }
  299.  
  300. // ******************************  Paths ********************************
  301.  
  302. char *elem_path (char *parent_path, sos_String name)
  303. {  char *path = new char [strlen (parent_path) + name.get_length() + 2];
  304.    char *s = name.make_Cstring();
  305.    strcpy (path, parent_path);
  306.    if (strlen (parent_path) > 1) strcat (path, "/");
  307.    strcat (path, s);
  308.    delete s;
  309.    return path;
  310. }
  311.  
  312. // *************************  Object Menues  ****************************
  313.  
  314. object_menu::~object_menu()
  315. {  for (int i=0; i<nr_comps; i++)
  316.       delete sl[i];
  317.    delete path;
  318.    delete names;
  319.    delete sl;
  320. }
  321.  
  322. void omi_list::clear ()
  323. {  omi = 0;
  324.    nr_items = 0;
  325. }
  326.  
  327. void omi_list::insert (sos_String name, char *s)
  328. {  if (nr_items % 10 == 0)
  329.    {  object_menu_item *new_omi = new object_menu_item [nr_items+10];
  330.       for (int i=0; i<nr_items; i++)
  331.          new_omi[i] = omi[i];
  332.       delete omi;
  333.       omi = new_omi;
  334.    }
  335.    omi [nr_items].s = new char [strlen(s)+1];
  336.    strcpy (omi [nr_items].s, s);
  337.    omi [nr_items].name = name;
  338.    nr_items++;
  339. }
  340.  
  341. void omi_list::print (char *s)
  342. {  char *new_str = new char [strlen (s) + strlen (omi [nr_items-1].s) + 1];
  343.    strcpy (new_str, omi [nr_items-1].s);
  344.    strcat (new_str, s);
  345.    delete omi [nr_items-1].s;
  346.    omi [nr_items-1].s = new_str;
  347. }
  348.  
  349. void omi_list::print (smg_String &s)
  350. {  print (s.make_Cstring(SMG_BORROW));
  351. }
  352.  
  353. static int compare_omi (void *c1, void *c2)
  354. {  return strcmp (((object_menu_item*)c1)->s, ((object_menu_item*)c2)->s);
  355. }
  356.  
  357. void omi_list::make_object_menu (object_menu *om)
  358. {  qsort (&omi[1], nr_items-1, sizeof(object_menu_item), compare_omi);
  359.    char **sl = new char* [nr_items];
  360.    sos_String *names = new sos_String [nr_items];
  361.    om->nr_comps = nr_items;
  362.    om->sl = sl;
  363.    om->names = names;
  364.    for (int i=0; i<nr_items; i++)
  365.    {  sl[i] = omi[i].s;
  366.       names[i] = omi[i].name;
  367.    }
  368. }
  369.  
  370. void object_callback (Widget w, caddr_t client_data, caddr_t call_data)
  371. {  int i = ((XawListReturnStruct*) call_data)->list_index;
  372.    object_menu *om = (object_menu*) client_data;
  373.  
  374.    XawListUnhighlight (w);
  375.  
  376.    if (i == 0)
  377.    {  position pos = position::at_widget (w);
  378.       XawListHighlight (ocmd_menu, 0);
  379.       XtMoveWidget (ocmd_menu, pos.x, pos.y);
  380.       XtMapWidget (ocmd_menu);
  381.       XRaiseWindow (XtDisplay (ocmd_menu), XtWindow (ocmd_menu));
  382.       XtAddGrab (ocmd_menu, TRUE, FALSE);
  383.       ocmd_current_menu = om;
  384.    }
  385.    else
  386.    {  sos_Directory dir = sos_Object_Directory::make (om->o);
  387.       char *path = elem_path (om->path, om->names[i]);
  388.       display_object_menu
  389.      (dir [om->names[i]], dir, om->names[i], path, position::next_to (w));
  390.    }
  391. }
  392.  
  393. // **********************  Object Command Menu  *************************
  394.  
  395. void new_directory (object_menu *om)
  396. {  sos_String name = smg_String (txt_string).make_String (TEMP_CONTAINER);
  397.    sos_Container new_cnt = sos_Container::create();
  398.    sos_Directory new_dir = sos_Object_Directory::create (new_cnt, name);
  399.    new_cnt.close();
  400.    sos_Directory this_dir = sos_Object_Directory::make (om->o);
  401.    sos_Container this_ct = this_dir.container();
  402.    this_ct.open (WRITING, WAITING);
  403.    this_dir.insert (name, new_dir);
  404.    this_ct.close ();
  405.  
  406.    Widget this_w = om->w;
  407.    char *path = elem_path (om->path, name);
  408.    display_object_menu
  409.       (new_dir, this_dir, name, path, position::next_to (this_w));
  410.    redisplay_object_menu (om);
  411. }
  412.  
  413. sos_Bool move_elem (object_menu *om)
  414. {  sos_Bool error = FALSE;
  415.    sos_String dest_str =
  416.       smg_String (txt_string).make_String (TEMP_CONTAINER);
  417.    sos_Object dest_o = sos_Object_Directory::lookup (dest_str);
  418.    if (dest_o == NO_OBJECT OR NOT dest_o.is_some (sos_Object_Directory_type))
  419.    {  display_info ("destination directory does not exist");
  420.       error = TRUE;
  421.    }
  422.    else
  423.    {  sos_Directory dest_dir = sos_Object_Directory::make (dest_o);
  424.       om->parent = dest_dir;
  425.       char *path = elem_path (txt_string, om->name);
  426.       delete om->path;
  427.       om->path = path;
  428.       sos_Container cnt = dest_dir.container();
  429.       cnt.open (WRITING, WAITING);
  430.       dest_dir.insert (om->name, om->o);
  431.       cnt.close ();
  432.       cnt = om->parent.container();
  433.       cnt.open (WRITING, WAITING);
  434.       om->parent.remove (om->name);
  435.       cnt.close ();
  436.       redisplay_object_menu (displayed_objects.menu (om->parent));
  437.       redisplay_object_menu (displayed_objects.menu (dest_dir));
  438.       redisplay_object_menu (om, TRUE);
  439.    }
  440.    return error;
  441. }
  442.  
  443. void remove_elem (object_menu *om)
  444. {  sos_Container parent_cnt = om->parent.container();
  445.    parent_cnt.open (WRITING, WAITING);
  446.    om->parent.remove (om->name);
  447.    parent_cnt.close ();
  448.    redisplay_object_menu (displayed_objects.menu (om->parent));
  449.    delete_object_menu (om);
  450. }
  451.  
  452. void ocmd_callback (Widget, caddr_t, caddr_t call_data)
  453. {  ocmd_cmd = ocmd_cmds (((XawListReturnStruct*) call_data)->list_index);
  454.    object_menu *om = ocmd_current_menu;
  455.  
  456.    XtRemoveGrab (ocmd_menu);
  457.    XtUnmapWidget (ocmd_menu);
  458.  
  459.    sos_Object o, parent;
  460.  
  461.    switch (ocmd_cmd)
  462.    {  case ocmd_DIRECTORY:
  463.      break;
  464.       case ocmd_NEW:
  465.      o = om->o;
  466.      if (NOT o.is_some (sos_Object_Directory_type))
  467.         display_info ("no directory");
  468.      else
  469.         display_txt_menu();
  470.      break;
  471.       case ocmd_DELETE:
  472.      o = om->o;
  473.      parent = om->parent;
  474.      if (NOT o.is_some (sos_Object_Directory_type))
  475.         display_info ("no directory");
  476.      else if (parent == NO_OBJECT)
  477.         display_info ("root directory must not be deleted");
  478.      else
  479.      {  remove_elem (om);
  480.         sos_Container cnt = o.container();
  481.         cnt.open (WRITING, WAITING);
  482.         o.destroy();
  483.         cnt.close ();
  484.      }
  485.      break;
  486.       case ocmd_MOVE:
  487.      parent = om->parent;
  488.      if (parent == NO_OBJECT)
  489.         display_info ("root directory must not be moved");
  490.      else
  491.         display_txt_menu();
  492.      break;
  493.       case ocmd_REMOVE:
  494.      parent = om->parent;
  495.      if (parent == NO_OBJECT)
  496.         display_info ("root directory must not be removed");
  497.      else
  498.         remove_elem (om);
  499.      break;
  500.       case ocmd_QUIT:
  501.      delete_object_menu (om);
  502.      break;
  503.       case ocmd_CLOSE:
  504.      XtUnmapWidget (om->w);
  505.      om->is_open = FALSE;
  506.      break;
  507.       default:
  508.      break;
  509.    }
  510. }
  511.  
  512. // *************************  Dumped Objects  ***************************
  513.  
  514. void displayed_object_list::insert (object_menu *om, Widget w)
  515. {  displayed_object_list *ol = new displayed_object_list;
  516.    ol->next = next;
  517.    ol->om = om;
  518.    ol->w = w;
  519.    next = ol;
  520.    number++;
  521. }
  522.  
  523. void displayed_object_list::remove (object_menu *om)
  524. {  for (displayed_object_list *ol = this; ol->next; ol=ol->next)
  525.       if (ol->next->om == om)
  526.       {  displayed_object_list *od = ol->next;
  527.      ol->next = ol->next->next;
  528.      XtDestroyWidget (od->w);
  529.      delete od;
  530.      delete om;
  531.      return;
  532.       }
  533. }
  534.  
  535. Widget displayed_object_list::widget (sos_Object o)
  536. {  for (displayed_object_list *ol = next; ol; ol=ol->next)
  537.       if (ol->om->o == o)
  538.      return ol->w;
  539.    return NULL;
  540. }
  541.  
  542. object_menu* displayed_object_list::menu (sos_Object o)
  543. {  for (displayed_object_list *ol = next; ol; ol=ol->next)
  544.       if (ol->om->o == o)
  545.      return ol->om;
  546.    return 0;
  547. }
  548.  
  549. // ************************  Widget Positions  **************************
  550.  
  551. position position::root ()
  552. {  position result;
  553.    result.x = default_distance;
  554.    result.y = default_distance;
  555.    return result;
  556. }
  557.  
  558. position position::at_widget (Widget w)
  559. {  ac=0;
  560.    position result;
  561.    int width;
  562.  
  563.    XtSetArg (al[ac], XtNhorizDistance, &result.x); inc_ac();
  564.    XtSetArg (al[ac], XtNvertDistance, &result.y); inc_ac();
  565.    XtSetArg (al[ac], XtNwidth, &width); inc_ac();
  566.    XtGetValues (w, al, ac);
  567.    return result;
  568. }
  569.  
  570. position position::next_to (Widget w)
  571. {  ac=0;
  572.    position result;
  573.    Dimension width;
  574.  
  575.    XtSetArg (al[ac], XtNhorizDistance, &result.x); inc_ac();
  576.    XtSetArg (al[ac], XtNvertDistance, &result.y); inc_ac();
  577.    XtSetArg (al[ac], XtNwidth, &width); inc_ac();
  578.    XtGetValues (w, al, ac);
  579.    result.x += width + default_distance;
  580.    return result;
  581. }
  582.  
  583. // *******************  Display Object Components  **********************
  584.  
  585. void display_elements (sos_Directory d)
  586. {  agg_iterate_association (d, sos_String name, sos_Object elem)
  587.    {  omis.insert (name, "");
  588.       omis.print (name.make_Cstring());
  589.       omis.print (" (");
  590.       omis.print (elem.type().get_name().make_Cstring());
  591.       omis.print (")");
  592.    }
  593.    agg_iterate_association_end (d, name, elem);
  594. }
  595.  
  596. void redisplay_object_menu (object_menu *om, sos_Bool moved /* = FALSE */)
  597. {  if (om != 0)
  598.    {  char *path = strdup (om->path);
  599.       sos_Object om_o = om->o;
  600.       sos_Directory om_parent = om->parent;
  601.       sos_String om_name = om->name;
  602.       Widget om_w = om->w;
  603.       sos_Bool om_is_open = om->is_open;
  604.       displayed_objects.remove (om);
  605.       display_object_menu
  606.      (om_o, om_parent, om_name,
  607.       path, position::at_widget (om_w));
  608.       if (NOT om_is_open)
  609.       {  om = displayed_objects.menu (om_o);
  610.      XtUnmapWidget (om->w);
  611.      om->is_open = FALSE;
  612.       }
  613.      
  614.       if (moved AND om_o.is_some (sos_Object_Directory_type))
  615.       {  sos_Directory dir = sos_Object_Directory::make (om_o);
  616.      agg_iterate_association (dir, sos_String name, sos_Object elem)
  617.      {  om = displayed_objects.menu (elem);
  618.         if (om != 0)
  619.         {  om->path = elem_path (path, name);
  620.            redisplay_object_menu (om, TRUE);
  621.         }
  622.      }
  623.      agg_iterate_association_end (dir, name, elem);
  624.       }
  625.    }
  626. }
  627.  
  628. void delete_object_menu (object_menu *om)
  629. {  if (om != 0)
  630.    {  sos_Object om_o = om->o;
  631.       displayed_objects.remove (om);
  632.       if (om_o.is_some (sos_Object_Directory_type))
  633.       {  sos_Directory dir = sos_Object_Directory::make (om_o);
  634.      agg_iterate_association (dir, sos_String name, sos_Object elem)
  635.      {  delete_object_menu (displayed_objects.menu (elem));
  636.      }
  637.      agg_iterate_association_end (dir, name, elem);
  638.       }
  639.    }
  640. }
  641.  
  642. void display_object_menu (sos_Object o,
  643.               sos_Directory parent,
  644.               sos_String name,
  645.               char *path,
  646.               position pos)
  647. {  if (o == NO_OBJECT) return;
  648.  
  649.    // determine new window position
  650.  
  651.    object_menu *om = displayed_objects.menu (o);
  652.    if (om) // object is already displayed
  653.    {  Widget wo = displayed_objects.widget (o);
  654.       XtMoveWidget (wo, pos.x, pos.y);
  655.       XRaiseWindow (XtDisplay (wo), XtWindow (wo));
  656.       ac=0;
  657.       XtSetArg (al[ac], XtNhorizDistance, pos.x); inc_ac();
  658.       XtSetArg (al[ac], XtNvertDistance, pos.y); inc_ac();
  659.       XtSetValues (wo, al, ac);
  660.       XtUnmanageChild (wo);
  661.       XtManageChild (wo);
  662.    }
  663.    else // construct new object widget
  664.    {  omis.clear();
  665.  
  666.       omis.insert (sos_String::make (NO_OBJECT), path);
  667.       if (o.is_some (sos_Object_Directory_type))
  668.      display_elements (sos_Object_Directory::make (o));
  669.       else
  670.       {  omis.print (" (");
  671.      omis.print (o.type().get_name().make_Cstring());
  672.      omis.print (")");
  673.       }
  674.  
  675.       object_menu *om = new object_menu;
  676.       om->o = o;
  677.       om->is_open = TRUE;
  678.       om->name = name;
  679.       om->parent = parent;
  680.       om->path = path;
  681.       omis.make_object_menu (om);
  682.  
  683.       ac=0;
  684.       XtSetArg (al[ac], XtNnumberStrings, omis.nr_items); inc_ac();
  685.       XtSetArg (al[ac], XtNlist, om->sl); inc_ac();
  686.       XtSetArg (al[ac], XtNverticalList, TRUE); inc_ac();
  687.       XtSetArg (al[ac], XtNforceColumns, TRUE); inc_ac();
  688.       XtSetArg (al[ac], XtNdefaultColumns, 1); inc_ac();
  689.  
  690.       XtSetArg (al[ac], XtNtop, XtChainTop); inc_ac();
  691.       XtSetArg (al[ac], XtNbottom, XtChainTop); inc_ac();
  692.       XtSetArg (al[ac], XtNleft, XtChainLeft); inc_ac();
  693.       XtSetArg (al[ac], XtNright, XtChainLeft); inc_ac();
  694.  
  695.       XtSetArg (al[ac], XtNhorizDistance, pos.x); inc_ac();
  696.       XtSetArg (al[ac], XtNvertDistance, pos.y); inc_ac();
  697.  
  698.       XtSetArg (al[ac], XtNborderWidth, 2); inc_ac();
  699.       XtSetArg (al[ac], XtNborderColor, red_pxl); inc_ac();
  700.       XtSetArg (al[ac], XtNforeground, blue_pxl); inc_ac();
  701.  
  702.       char name [20];
  703.       sprintf (name, "o%d", object_nr);
  704.       object_nr++;
  705.  
  706.       om->w = XtCreateManagedWidget
  707.          (name, listWidgetClass, form_wdgt, al, ac);
  708.       XtAddCallback (om->w, XtNcallback,
  709.              (XtCallbackProc) object_callback, (caddr_t) om);
  710.       XtAddEventHandler (om->w, ButtonPressMask, FALSE,
  711.              (XtEventHandler) drag_object, NULL);
  712.  
  713.       XRaiseWindow (XtDisplay (om->w), XtWindow (om->w));
  714.       displayed_objects.insert (om, om->w);
  715.    }
  716. }
  717.  
  718. // ****************************  Menues  ********************************
  719.  
  720. void menu_list_callback (Widget w, caddr_t client_data, caddr_t call_data)
  721. {  XawListReturnStruct *l = (XawListReturnStruct*) call_data;
  722.    hdr_cmds hdr_cmd = hdr_cmds (client_data);
  723.  
  724.    XawListUnhighlight (w);
  725.  
  726.    XtRemoveGrab (menu_header[0]);
  727.    open_menu = nr_menues;
  728.    XtUnmapWidget (w);
  729.  
  730.    switch (hdr_cmd)
  731.    {  case hdr_FILE:
  732.      file_cmds file_cmd = file_cmds (l->list_index);
  733.      switch (file_cmd)
  734.      {  case file_ROOT:
  735.            display_root();
  736.            break;
  737.         case file_QUIT:
  738.            exit (0);
  739.            break;
  740.         default:
  741.            break;
  742.      }
  743.      break;
  744.       default:
  745.      break;
  746.    }
  747. }
  748.  
  749. void menu_header_callback (Widget, caddr_t client_data, caddr_t)
  750. {  int i = (int) client_data;
  751.    Widget lw = menu_list[i];
  752.  
  753.    if (i == open_menu)
  754.    {  XtRemoveGrab (menu_header[0]);
  755.       open_menu = nr_menues;
  756.       XtUnmapWidget (lw);
  757.    }
  758.    else
  759.    {  if (open_menu < nr_menues)
  760.       {  XtRemoveGrab (menu_list[open_menu]);
  761.      XtUnmapWidget (menu_list[open_menu]);
  762.       }
  763.       else
  764.       {  for (int j=0; j<nr_menues; j++)
  765.         XtAddGrab (menu_header[j], FALSE, FALSE);
  766.       }
  767.       open_menu = i;
  768.       XtMapWidget (lw);
  769.       XRaiseWindow (XtDisplay (lw), XtWindow (lw));
  770.       XtAddGrab (lw, FALSE, FALSE);
  771.    }
  772. }
  773.  
  774. void install_header_menues ()
  775. {  char name[20];
  776.    Widget w;
  777.  
  778.    for (int i=0; i<nr_menues; i++)
  779.    {  if (i==0) w = NULL;
  780.       else w = menu_header[i-1];
  781.  
  782.       ac=0;
  783.       XtSetArg (al[ac], XtNborderWidth, 0); inc_ac();
  784.       XtSetArg (al[ac], XtNlabel, menu_header_items[i]); inc_ac();
  785.       XtSetArg (al[ac], XtNfromHoriz, w); inc_ac();
  786.       XtSetArg (al[ac], XtNhorizDistance, 0); inc_ac();
  787.       XtSetArg (al[ac], XtNvertDistance, 0); inc_ac();
  788.       XtSetArg (al[ac], XtNtop, XtChainTop); inc_ac();
  789.       XtSetArg (al[ac], XtNbottom, XtChainTop); inc_ac();
  790.       XtSetArg (al[ac], XtNleft, XtChainLeft); inc_ac();
  791.       XtSetArg (al[ac], XtNright, XtChainLeft); inc_ac();
  792.  
  793.       XtSetArg (al[ac], XtNforeground, red_pxl); inc_ac();
  794.  
  795.       sprintf (name, "menu_label%d", i);
  796.       menu_header[i] = XtCreateManagedWidget
  797.          (name, commandWidgetClass, app_form_wdgt, al, ac);
  798.       XtAddCallback (menu_header[i], XtNcallback,
  799.              (XtCallbackProc) menu_header_callback, (caddr_t) i);
  800.  
  801.       ac=0;
  802.       XtSetArg (al[ac], XtNlist, menu_list_items[i]); inc_ac();
  803.       XtSetArg (al[ac], XtNverticalList, TRUE); inc_ac();
  804.       XtSetArg (al[ac], XtNforceColumns, TRUE); inc_ac();
  805.       XtSetArg (al[ac], XtNdefaultColumns, 1); inc_ac();
  806.       XtSetArg (al[ac], XtNmappedWhenManaged, FALSE); inc_ac();
  807.       XtSetArg (al[ac], XtNfromHoriz, w); inc_ac();
  808.       XtSetArg (al[ac], XtNfromVert, menu_header[i]); inc_ac();
  809.       XtSetArg (al[ac], XtNhorizDistance, 0); inc_ac();
  810.       XtSetArg (al[ac], XtNvertDistance, 0); inc_ac();
  811.       XtSetArg (al[ac], XtNtop, XtChainTop); inc_ac();
  812.       XtSetArg (al[ac], XtNbottom, XtChainTop); inc_ac();
  813.       XtSetArg (al[ac], XtNleft, XtChainLeft); inc_ac();
  814.       XtSetArg (al[ac], XtNright, XtChainLeft); inc_ac();
  815.  
  816.       XtSetArg (al[ac], XtNborderWidth, 2); inc_ac();
  817.       XtSetArg (al[ac], XtNborderColor, red_pxl); inc_ac();
  818.       XtSetArg (al[ac], XtNforeground, green_pxl); inc_ac();
  819.  
  820.       sprintf (name, "menu_list%d", i);
  821.       menu_list[i] = XtCreateManagedWidget
  822.             (name, listWidgetClass, app_form_wdgt, al, ac);
  823.       XtAddCallback (menu_list[i], XtNcallback,
  824.              (XtCallbackProc) menu_list_callback, (caddr_t) i);
  825.    }
  826. }
  827.  
  828. static void install_ocmd_menu ()
  829. {  ac=0;
  830.    XtSetArg (al[ac], XtNlist, ocmd_menu_items); inc_ac();
  831.    XtSetArg (al[ac], XtNverticalList, TRUE); inc_ac();
  832.    XtSetArg (al[ac], XtNforceColumns, TRUE); inc_ac();
  833.    XtSetArg (al[ac], XtNdefaultColumns, 1); inc_ac();
  834.    XtSetArg (al[ac], XtNmappedWhenManaged, FALSE); inc_ac();
  835.    XtSetArg (al[ac], XtNtop, XtChainTop); inc_ac();
  836.    XtSetArg (al[ac], XtNbottom, XtChainTop); inc_ac();
  837.    XtSetArg (al[ac], XtNleft, XtChainLeft); inc_ac();
  838.    XtSetArg (al[ac], XtNright, XtChainLeft); inc_ac();
  839.    ocmd_menu = XtCreateManagedWidget
  840.          ("ocmd", listWidgetClass, form_wdgt, al, ac);
  841.    XtAddCallback (ocmd_menu, XtNcallback,
  842.           (XtCallbackProc) ocmd_callback, NULL);
  843. }
  844.  
  845. // **************************  Dialogues  *******************************
  846.  
  847. void txt_cancel_callback (Widget, caddr_t, caddr_t)
  848. {  XtRemoveGrab (txt_menu_wdgts.main);
  849.    XtUnmapWidget (txt_menu_wdgts.main);
  850. }
  851.  
  852. void txt_do_callback (Widget, caddr_t, caddr_t)
  853. {  object_menu *om = ocmd_current_menu;
  854.    sos_Bool error = FALSE;
  855.  
  856.    err_block
  857.    {  switch (ocmd_cmd)
  858.       {  case ocmd_NEW:
  859.         new_directory (om);
  860.         break;
  861.      case ocmd_MOVE:
  862.         error = move_elem (om);
  863.         break;
  864.      default:
  865.         break;
  866.       }
  867.    }
  868.    err_exception
  869.    {  display_info(err_last_raised());
  870.       error = TRUE;
  871.    }
  872.    err_block_end
  873.  
  874.    if (NOT error)
  875.    {  XtRemoveGrab (txt_menu_wdgts.main);
  876.       XtUnmapWidget (txt_menu_wdgts.main);
  877.    }
  878. }
  879.  
  880. void display_txt_menu()
  881. {  XawTextBlock tb;
  882.    tb.firstPos = 0;
  883.    tb.length = 0;
  884.    tb.ptr = 0;
  885.    tb.format = FMT8BIT;
  886.    XawTextReplace (txt_menu_wdgts.txt, 0, strlen (txt_string), &tb);
  887.  
  888.    XtMapWidget (txt_menu_wdgts.main);
  889.    XRaiseWindow (XtDisplay (txt_menu_wdgts.main),
  890.          XtWindow (txt_menu_wdgts.main));
  891.  
  892.    XtAddGrab (txt_menu_wdgts.main, TRUE, FALSE);
  893. }
  894.  
  895. void install_dialogues ()
  896. {  Widget cancel_but, do_but, name_lab;
  897.  
  898.    // ******************* txt dialogue *************************
  899.  
  900.    ac=0;
  901.    XtSetArg (al[ac], XtNvertDistance, 30); inc_ac();
  902.    XtSetArg (al[ac], XtNhorizDistance, 30); inc_ac();
  903.    XtSetArg (al[ac], XtNtop, XtChainTop); inc_ac();
  904.    XtSetArg (al[ac], XtNbottom, XtChainTop); inc_ac();
  905.    XtSetArg (al[ac], XtNleft, XtChainLeft); inc_ac();
  906.    XtSetArg (al[ac], XtNright, XtChainLeft); inc_ac();
  907.    XtSetArg (al[ac], XtNmappedWhenManaged, FALSE); inc_ac();
  908.    txt_menu_wdgts.main = XtCreateManagedWidget
  909.          ("txt.main", formWidgetClass, form_wdgt, al, ac);
  910.    XtAddEventHandler (txt_menu_wdgts.main, ButtonPressMask, FALSE,
  911.               (XtEventHandler) drag_object, NULL);
  912.  
  913.    ac=0;
  914.    XtSetArg (al[ac], XtNlabel, "name"); inc_ac();
  915.    XtSetArg (al[ac], XtNborderWidth, 0); inc_ac();
  916.    name_lab = XtCreateManagedWidget
  917.         ("txt.name_lab", labelWidgetClass, txt_menu_wdgts.main, al, ac);
  918.  
  919.    ac=0;
  920.    XtSetArg (al[ac], XtNlength, txt_length); inc_ac();
  921.    XtSetArg (al[ac], XtNstring, txt_string); inc_ac();
  922.    XtSetArg (al[ac], XtNwidth, 200); inc_ac();
  923.    XtSetArg (al[ac], XtNfromHoriz, name_lab); inc_ac();
  924.    XtSetArg (al[ac], XtNeditType, XawtextEdit); inc_ac();
  925.    XtSetArg (al[ac], XtNscrollHorizontal, TRUE); inc_ac();
  926.    XtSetArg (al[ac], XtNheight, 30); inc_ac();
  927.    txt_menu_wdgts.txt = XtCreateManagedWidget
  928.         ("txt.txt", asciiStringWidgetClass, txt_menu_wdgts.main, al, ac);
  929.    XawTextEnableRedisplay (txt_menu_wdgts.txt);
  930.  
  931.    ac=0;
  932.    XtSetArg (al[ac], XtNlabel, "  do  "); inc_ac();
  933.    XtSetArg (al[ac], XtNfromVert, txt_menu_wdgts.txt); inc_ac();
  934.    do_but = XtCreateManagedWidget
  935.         ("txt.do", commandWidgetClass, txt_menu_wdgts.main, al, ac);
  936.    XtAddCallback (do_but, XtNcallback,
  937.           (XtCallbackProc) txt_do_callback, NULL);
  938.  
  939.    ac=0;
  940.    XtSetArg (al[ac], XtNlabel, "cancel"); inc_ac();
  941.    XtSetArg (al[ac], XtNfromVert, txt_menu_wdgts.txt); inc_ac();
  942.    XtSetArg (al[ac], XtNfromHoriz, do_but); inc_ac();
  943.    XtSetArg (al[ac], XtNhorizDistance, 20); inc_ac();
  944.    cancel_but = XtCreateManagedWidget
  945.         ("txt.cancel", commandWidgetClass, txt_menu_wdgts.main, al, ac);
  946.    XtAddCallback (cancel_but, XtNcallback,
  947.           (XtCallbackProc) txt_cancel_callback, NULL);
  948.  
  949. }
  950.  
  951. void display_root()
  952. {  display_object_menu
  953.       (sos_Object_Directory::root(),
  954.        sos_Object_Directory::make (NO_OBJECT),
  955.        sos_String::make (NO_OBJECT),
  956.        strdup ("/"),
  957.        position::root());
  958. }
  959.  
  960. void display_info (err_msg msg)
  961. {  strncpy (info_string, msg, info_length);
  962.    info_string [info_length] = 0;
  963.    ac=0;
  964.    XtSetArg (al[ac], XtNlabel, info_string); inc_ac();
  965.    XtSetValues (info_line_wdgt, al, ac);
  966. }
  967.  
  968. // *****************************  Main  *********************************
  969.  
  970. main (int argc, char *argv[])
  971. {  Widget        app_shell;
  972.    Widget        app_view;
  973.  
  974.    sos_init (argc, argv);
  975.  
  976.    app_shell = XtInitialize ("main", "Dir", NULL, 0, (Cardinal*) &argc, argv);
  977.  
  978.    Display *disp = XtDisplay (app_shell);
  979.    Colormap cmap = DefaultColormap (disp, 0);
  980.    XColor color, exact;
  981.    XAllocNamedColor (disp, cmap, "red", &color, &exact);
  982.    red_pxl = color.pixel;
  983.    XAllocNamedColor (disp, cmap, "forest green", &color, &exact);
  984.    green_pxl = color.pixel;
  985.    XAllocNamedColor (disp, cmap, "blue", &color, &exact);
  986.    blue_pxl = color.pixel;
  987.  
  988.    ac=0;
  989.    XtSetArg (al[ac], XtNdefaultDistance, 0); inc_ac();
  990.    app_form_wdgt = XtCreateManagedWidget
  991.            ("app_form", formWidgetClass, app_shell, al, ac);
  992.  
  993.    install_header_menues ();
  994.  
  995.    ac=0;
  996.    XtSetArg (al[ac], XtNforceBars, TRUE); inc_ac();
  997.    XtSetArg (al[ac], XtNallowHoriz, TRUE); inc_ac();
  998.    XtSetArg (al[ac], XtNallowVert, TRUE); inc_ac();
  999.    XtSetArg (al[ac], XtNuseBottom, TRUE); inc_ac();
  1000.    XtSetArg (al[ac], XtNuseRight, TRUE); inc_ac();
  1001.    XtSetArg (al[ac], XtNheight, 500); inc_ac();
  1002.    XtSetArg (al[ac], XtNwidth, 800); inc_ac();
  1003.    XtSetArg (al[ac], XtNfromVert, menu_header[0]); inc_ac();
  1004.    XtSetArg (al[ac], XtNtop, XtChainTop); inc_ac();
  1005.    XtSetArg (al[ac], XtNbottom, XtChainBottom); inc_ac();
  1006.    XtSetArg (al[ac], XtNleft, XtChainLeft); inc_ac();
  1007.    XtSetArg (al[ac], XtNright, XtChainRight); inc_ac();
  1008.    app_view = XtCreateManagedWidget
  1009.            ("app_view", viewportWidgetClass, app_form_wdgt, al, ac);
  1010.  
  1011.    ac=0;
  1012.    XtSetArg (al[ac], XtNdefaultDistance, default_distance); inc_ac();
  1013.    form_wdgt = XtCreateManagedWidget
  1014.            ("form", formWidgetClass, app_view, al, ac);
  1015.  
  1016.    install_dialogues ();
  1017.    install_ocmd_menu ();
  1018.  
  1019.    strcpy (info_string, "");
  1020.    ac=0;
  1021.    XtSetArg (al[ac], XtNlabel, info_string); inc_ac();
  1022.    XtSetArg (al[ac], XtNborderWidth, 0); inc_ac();
  1023.    XtSetArg (al[ac], XtNwidth, 800); inc_ac();
  1024.    XtSetArg (al[ac], XtNjustify, XtJustifyLeft); inc_ac();
  1025.    XtSetArg (al[ac], XtNfromVert, app_view); inc_ac();
  1026.    XtSetArg (al[ac], XtNtop, XtChainTop); inc_ac();
  1027.    XtSetArg (al[ac], XtNbottom, XtChainBottom); inc_ac();
  1028.    XtSetArg (al[ac], XtNleft, XtChainLeft); inc_ac();
  1029.    XtSetArg (al[ac], XtNright, XtChainRight); inc_ac();
  1030.    info_line_wdgt = XtCreateManagedWidget
  1031.         ("info_line", labelWidgetClass, app_form_wdgt, al, ac);
  1032.  
  1033.    XtRealizeWidget (app_shell);
  1034.  
  1035.    display_root();
  1036.  
  1037.    XtMainLoop ();
  1038.  
  1039.    exit (0);
  1040. }
  1041.